package link

import (
	"fmt"
	"math/rand"
	"time"
)

type DoubleLinkedList struct {
	Head *DoubleLinkedNode
}

func NewDoubleLinkedList() *DoubleLinkedList {
	return &DoubleLinkedList{Head: NewDoubleLinkedNode(0)}
}

func (dll *DoubleLinkedList) CreateDoubleLinkedList(nlen int) {
	rand.Seed(time.Now().Unix())
	cNode := dll.Head
	for i := 0; i < nlen; i++ {
		node := NewDoubleLinkedNode(rand.Intn(100) + 1)
		cNode.Next = node
		node.Prev = cNode
		cNode = cNode.Next
	}
}

func (dll *DoubleLinkedList) CreateDoubleLinkedListWithNumSeq(nlen int) {
	rand.Seed(time.Now().Unix())
	cNode := dll.Head
	for i := 0; i < nlen; i++ {
		node := NewDoubleLinkedNode(i + 1)
		cNode.Next = node
		node.Prev = cNode
		cNode = cNode.Next
	}
}

func (dll *DoubleLinkedList) TravelDoubleLinkedList() {
	cNode := dll.Head
	fmt.Printf("该节点为：head")
	for cNode.Next != nil {
		if cNode.Data != 0 {
			fmt.Printf("->%v", cNode.Data)
		}
		cNode = cNode.Next
	}
	fmt.Printf("->%v\n", cNode.Data)
}

func (dll *DoubleLinkedList) InsertElementInHead(num int) {
	if num == 0 {
		rand.Seed(time.Now().Unix())
		num = rand.Intn(100) + 1
	}
	fmt.Println("头插法，插入元素：", num)
	node := NewDoubleLinkedNode(num)
	cNode := dll.Head
	node.Next = cNode.Next
	cNode.Next.Prev = node
	cNode.Next = node
	node.Prev = cNode
}

func (dll *DoubleLinkedList) InsertElementInTail(num int) {
	if num == 0 {
		rand.Seed(time.Now().Unix())
		num = rand.Intn(100) + 1
	}
	fmt.Println("尾插法，插入元素：", num)
	node := NewDoubleLinkedNode(num)
	cNode := dll.Head
	for cNode.Next != nil {
		cNode = cNode.Next
	}
	cNode.Next = node
	node.Prev = cNode
}

func (dll *DoubleLinkedList) IsEmpty() bool {
	return dll.Head.Next == nil
}

func (dll *DoubleLinkedList) GetLength() int {
	cNode := dll.Head
	nlen := 0
	for cNode.Next != nil {
		nlen += 1
		cNode = cNode.Next
	}
	return nlen
}

func (dll *DoubleLinkedList) FindElemnentByPos(pos int) *DoubleLinkedNode {
	if dll.IsEmpty() {
		return nil
	}
	cNode := dll.Head
	ppos := 0
	for cNode.Next != nil {
		if ppos == pos {
			return cNode
		}
		ppos += 1
		cNode = cNode.Next
	}
	return nil
}

func (dll *DoubleLinkedList) FindElemnentPreNode(num int) *DoubleLinkedNode {
	if dll.IsEmpty() {
		return nil
	}
	cNode := dll.Head
	var preNode *DoubleLinkedNode
	for cNode.Next != nil {
		if cNode.Data == num {
			return preNode
		}
		preNode = cNode
		cNode = cNode.Next
	}
	return nil
}

func (dll *DoubleLinkedList) DeleteElement(num int) {
	fmt.Println("待删除元素： ", num)
	preNode := dll.FindElemnentPreNode(num)
	preNode.Next = preNode.Next.Next
	preNode.Next.Next.Prev = preNode
}
